﻿using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

using System.Web.Mvc.Html;
using System.Web.Routing;
using System.Xml.Linq;
using MVCMongo.Filters;


namespace System.Web.Mvc
{
    public static class HtmlExtensions
    {
        public static MvcHtmlString RadioButtonForSelectList<TModel, TProperty>(
           this HtmlHelper<TModel> htmlHelper,
           Expression<Func<TModel, TProperty>> expression,
           IEnumerable<SelectListItem> listOfValues)
        {
            var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            var sb = new StringBuilder();

            if (listOfValues != null)
            {
                // Create a radio button for each item in the list
                foreach (SelectListItem item in listOfValues)
                {
                    // Generate an id to be given to the radio button field
                    var id = string.Format("{0}_{1}", metaData.PropertyName, item.Value);

                    // Create and populate a radio button using the existing html helpers
                    var label = htmlHelper.Label(id, HttpUtility.HtmlEncode(item.Text));
                    var radio = htmlHelper.RadioButtonFor(expression, item.Value, new { id = id }).ToHtmlString();

                    // Create the html string that will be returned to the client
                    // e.g. <input data-val="true" data-val-required="You must select an option" id="TestRadio_1" name="TestRadio" type="radio" value="1" /><label for="TestRadio_1">Line1</label>
                    sb.AppendFormat("<div class=\"RadioButton\">{0}{1}</div>", radio, label);
                }
            }

            return MvcHtmlString.Create(sb.ToString());
        }

        #region Checkboxlist

        public static string CheckBoxList(this HtmlHelper htmlHelper, string name, List<CheckBoxListInfo> listInfo)
        {
            return htmlHelper.CheckBoxList(name, listInfo,
                ((IDictionary<string, object>)null));
        }

        public static string CheckBoxList(this HtmlHelper htmlHelper, string name, List<CheckBoxListInfo> listInfo,
            object htmlAttributes)
        {
            return htmlHelper.CheckBoxList(name, listInfo,
                ((IDictionary<string, object>)new RouteValueDictionary(htmlAttributes)));
        }

        public static string CheckBoxList(this HtmlHelper htmlHelper, string name, List<CheckBoxListInfo> listInfo,
           IDictionary<string, object> htmlAttributes)
        {
            if (String.IsNullOrEmpty(name))
                throw new ArgumentException("The argument must have a value", "name");
            if (listInfo == null)
                throw new ArgumentNullException("listInfo");
            if (listInfo.Count < 1)
                throw new ArgumentException("The list must contain at least one value", "listInfo");

            StringBuilder sb = new StringBuilder();

            foreach (CheckBoxListInfo info in listInfo)
            {
                TagBuilder b = new TagBuilder("label");
                TagBuilder builder = new TagBuilder("input");
                if (info.IsChecked) builder.MergeAttribute("checked", "checked");
                builder.MergeAttributes<string, object>(htmlAttributes);
                builder.MergeAttribute("type", "checkbox");
                builder.MergeAttribute("value", info.Value);
                builder.MergeAttribute("name", name);
                builder.InnerHtml = info.DisplayText;
                b.InnerHtml = builder.ToString(TagRenderMode.Normal);
                sb.Append(b.ToString(TagRenderMode.Normal));

                sb.Append("<div class='clearfix'></div>");
            }

            return sb.ToString();
        }
        #endregion

        public static MvcHtmlString DateTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null)
        {
            var mvcHtmlString = System.Web.Mvc.Html.InputExtensions.TextBoxFor(htmlHelper, expression, htmlAttributes ?? new { @class = "text-box single-line date-picker" });
            var xDoc = XDocument.Parse(mvcHtmlString.ToHtmlString());
            var xElement = xDoc.Element("input");
            if (xElement != null)
            {
                var valueAttribute = xElement.Attribute("value");
                if (valueAttribute != null)
                {
                    valueAttribute.Value = DateTime.Parse(valueAttribute.Value).ToString("MM/dd/yyyy");
                    if (valueAttribute.Value == "01/01/0001")
                        valueAttribute.Value = string.Empty;
                }
            }
            return new MvcHtmlString(xDoc.ToString());
        }

        public static MvcHtmlString DateHiddenFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null)
        {
            var mvcHtmlString = System.Web.Mvc.Html.InputExtensions.HiddenFor(htmlHelper, expression, htmlAttributes);
            var xDoc = XDocument.Parse(mvcHtmlString.ToHtmlString());
            var xElement = xDoc.Element("input");
            if (xElement != null)
            {
                var valueAttribute = xElement.Attribute("value");
                if (valueAttribute != null &&!string.IsNullOrEmpty(valueAttribute.Value))
                {
                    valueAttribute.Value = DateTime.Parse(valueAttribute.Value).ToString("MM/dd/yyyy");
                    if (valueAttribute.Value == "01/01/0001")
                        valueAttribute.Value = string.Empty;
                }
            }
            return new MvcHtmlString(xDoc.ToString());
        }

        public static MvcHtmlString DropdownListForCustom<TModel, TProperty>(
           this HtmlHelper<TModel> htmlHelper,
           Expression<Func<TModel, TProperty>> expression,
           IEnumerable<SelectListItem> listOfValues, object htmlAttributes = null)
        {
            var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            var metaDataValue = metaData.Model == null ? "0" : metaData.Model.ToString();
            List<SelectListItem> newValues=new List<SelectListItem>();

            foreach (SelectListItem item in listOfValues)
            {
                if(item.Value==metaDataValue)
                {
                    item.Selected = true;
                }
                else
                {
                    item.Selected = false;
                }
                newValues.Add(item);
            }
            return htmlHelper.DropDownListFor(expression,newValues,htmlAttributes);
            //var sb = new StringBuilder();
            //TagBuilder select = new TagBuilder("select");
            //select.MergeAttributes(new RouteValueDictionary(htmlAttributes));
            //string selected = string.Empty;
            //if (listOfValues != null)
            //{
            //    // Create a radio button for each item in the list
            //    foreach (SelectListItem item in listOfValues)
            //    {
            //        if (item.Value == metaData.Model.ToString())
            //        {
            //            selected = "selected='selected'";
            //        }
            //        else
            //        {
            //            selected = string.Empty;
            //        }
            //        sb.AppendFormat("<option value='{0}' {2}>{1}</option>", item.Value, item.Text, selected);
            //    }
            //}
            //select.InnerHtml = sb.ToString();
            //return MvcHtmlString.Create(select.ToString(TagRenderMode.Normal));
        }

        public static MvcHtmlString NumericTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null)
        {
            RouteValueDictionary routeValues = new RouteValueDictionary(htmlAttributes);
            routeValues.Add("autocomplete", "off");

            var mvcHtmlString = Html.InputExtensions.TextBoxFor(htmlHelper, expression, routeValues);
            var xDoc = XDocument.Parse(mvcHtmlString.ToHtmlString());
            var xElement = xDoc.Element("input");
            if (xElement != null)
            {
                var valueAttribute = xElement.Attribute("value");
                if (valueAttribute != null)
                {
                    if (valueAttribute.Value == "0")
                        valueAttribute.Value = string.Empty;
                }
            }
            return new MvcHtmlString(xDoc.ToString());
        }


        public static MvcHtmlString Custom_TextBoxFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, object htmlAttributes)
        {
            //Fetching the metadata related to expression. This includes name of the property, model value of the property as well.
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
            string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
            //Fetching the property name.
            string propertyName = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();

            //Creating a input tag using TagBuilder class.
            TagBuilder textBox = new TagBuilder("input");
            //Setting the tags property type to text to render textbox.
            textBox.Attributes.Add("type", "text");
            //Setting the name and id attribute.
            textBox.Attributes.Add("name", propertyName);
            textBox.Attributes.Add("id", propertyName);

            //Setting the value attribute of textbox with model value if present.
            if (metadata.Model != null)
            {
                textBox.Attributes.Add("value", metadata.Model.ToString());
            }
            textBox.MergeAttributes(new RouteValueDictionary(htmlAttributes));
            return MvcHtmlString.Create(textBox.ToString(TagRenderMode.Normal));
        }

        public static MvcHtmlString MultiSelectFor(this HtmlHelper htmlHelper, string name, List<CheckBoxListInfo> listInfo)
        {
            return htmlHelper.MultiSelectFor(name, listInfo,
                ((IDictionary<string, object>)null));
        }

        public static MvcHtmlString MultiSelectFor(this HtmlHelper htmlHelper, string name, List<CheckBoxListInfo> listInfo,
            object htmlAttributes)
        {
            return htmlHelper.MultiSelectFor(name, listInfo,
                ((IDictionary<string, object>)new RouteValueDictionary(htmlAttributes)));
        }

        public static MvcHtmlString MultiSelectFor(this HtmlHelper htmlHelper, string name, List<CheckBoxListInfo> listInfo,
           IDictionary<string, object> htmlAttributes)
        {
            if (String.IsNullOrEmpty(name))
                throw new ArgumentException("The argument must have a value", "name");
            if (listInfo == null)
                throw new ArgumentNullException("listInfo");
            if (listInfo.Count < 1)
                throw new ArgumentException("The list must contain at least one value", "listInfo");

            StringBuilder sb = new StringBuilder();
            ////
            TagBuilder select = new TagBuilder("select");
            select.MergeAttributes(new RouteValueDictionary(htmlAttributes));
            select.MergeAttribute("name", name);
            select.MergeAttribute("multiple", "multiple");
            string selected = string.Empty;
            
                // Create a radio button for each item in the list
                foreach (CheckBoxListInfo info in listInfo)
                {
                    if (info.IsChecked)
                    {
                        selected = "selected='selected'";
                    }
                    else
                    {
                        selected = string.Empty;
                    }
                    sb.AppendFormat("<option value='{0}' {2}>{1}</option>", info.Value, info.DisplayText, selected);
                }
            select.InnerHtml = sb.ToString();
            return MvcHtmlString.Create(select.ToString(TagRenderMode.Normal));

            ////
            //<select style="height:100px !important" name="SponsorIds" multiple="multiple" id="SponsorIds">
            //foreach (CheckBoxListInfo info in listInfo)
            //{
            //    //TagBuilder b = new TagBuilder("label");
            //    TagBuilder builder = new TagBuilder("input");
            //    if (info.IsChecked) builder.MergeAttribute("checked", "checked");
            //    builder.MergeAttributes<string, object>(htmlAttributes);
            //    builder.MergeAttribute("type", "checkbox");
            //    builder.MergeAttribute("value", info.Value);
            //    builder.MergeAttribute("name", name);
            //    builder.InnerHtml = info.DisplayText;
            //    b.InnerHtml = builder.ToString(TagRenderMode.Normal);
            //    sb.Append(b.ToString(TagRenderMode.Normal));

            //    sb.Append("<div class='clearfix'></div>");
            //}

        }

        #region Image Dropdown List

        public static string ImageDropdownList(this HtmlHelper htmlHelper, string name, List<CheckBoxListInfo> listInfo)
        {
            return htmlHelper.ImageDropdownList(name, listInfo,
                ((IDictionary<string, object>)null));
        }

        public static string ImageDropdownList(this HtmlHelper htmlHelper, string name, List<CheckBoxListInfo> listInfo,
            object htmlAttributes)
        {
            return htmlHelper.ImageDropdownList(name, listInfo,
                ((IDictionary<string, object>)new RouteValueDictionary(htmlAttributes)));
        }

        public static string ImageDropdownList(this HtmlHelper htmlHelper, string name, List<CheckBoxListInfo> listInfo,
           IDictionary<string, object> htmlAttributes)
        {
            if (String.IsNullOrEmpty(name))
                throw new ArgumentException("The argument must have a value", "name");
            if (listInfo == null)
                throw new ArgumentNullException("listInfo");
            if (listInfo.Count < 1)
                throw new ArgumentException("The list must contain at least one value", "listInfo");

            StringBuilder sb = new StringBuilder();
            TagBuilder b = new TagBuilder("select");
            b.MergeAttribute("id", "languages");
            foreach (CheckBoxListInfo info in listInfo)
            {
                TagBuilder builder = new TagBuilder("option");
                if (info.IsChecked) builder.MergeAttribute("selected", "selected");
                builder.MergeAttributes<string, object>(htmlAttributes);
                builder.MergeAttribute("value", info.Value);
                builder.MergeAttribute("data-image", "/Content/image-dropdown/images/msdropdown/icons/blank.gif");
                builder.MergeAttribute("data-imagecss", "flag "+info.Value);
                builder.InnerHtml = info.DisplayText;
                //b.InnerHtml = builder.ToString(TagRenderMode.Normal);
                sb.Append(builder.ToString(TagRenderMode.Normal));
            }
            b.InnerHtml = sb.ToString();
            return b.ToString();
        }
        #endregion
    }
}